/* Copyright (c) 2001-2005 Todd C. Stellanova, rawthought
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The  above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE. 
 * 
 * 
 * This software was originally modified no later than Sept 25, 2007.
 * 
 */

// Expand to define DJSR75 define
@DJSR75@
// Expand to define test define
@DTESTDEF@
// Expand to define logging define
@DLOGDEF@

//#ifdef DJSR75
package org.kablog.kgui;

import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.util.Vector;
import java.util.Enumeration;
import javax.microedition.io.*;
import javax.microedition.io.file.*;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Image;
import javax.microedition.midlet.*;

//#ifdef DLOGGING
import net.sf.jlogmicro.util.logging.Logger;
import net.sf.jlogmicro.util.logging.LogManager;
import net.sf.jlogmicro.util.logging.Level;
//#endif

import com.substanceofcode.rssreader.presentation.UiUtil;

public class KFileSelectorImpl 
 extends List
  implements KFileSelector, CommandListener
  , FileSystemListener, Runnable
{
	protected   Image UPDIR_IMAGE;
	protected   Image FOLDER_IMAGE;
	protected   Image FILE_IMAGE;

	protected static final String FILE_SEPARATOR = 
		(System.getProperty("file.separator")!=null)?  System.getProperty("file.separator"): "/";
	protected static final String FILE_SEPARATOR_ALT = "/";

	private final static String UP_DIR = "..";

	private final Command openCommand =
		UiUtil.getCmdRsc("cmd.open", Command.ITEM, 1);    

	private final Command cancelCommand =
		UiUtil.getCmdRsc("cmd.cancel", Command.CANCEL, 2);    

	private Vector rootsList = new Vector();

	// Stores the current root, if null we are showing all the roots
	private FileConnection currentRoot = null;
	protected String[] filePatterns = null;
	protected byte[] fileDataBlock = null;
	protected String selectedFile = null;
	protected String selectedURL = null;
	protected KViewParent parent = null;
	protected String title = null;
	protected String defaultDir = null;
	protected String iconDir = "";
	//#ifdef DTEST
	private static final boolean bDebug = false;
	//#endif
	protected boolean bCurFolderIsARoot = true;
	protected boolean itemSelected = false;
	protected boolean cancelCmd = false;
	protected Thread kThread = null;
	protected MIDlet midlet = null;

	//#ifdef DLOGGING
    private Logger logger = Logger.getLogger("KFileSelectorImpl");
    private boolean fineLoggable = logger.isLoggable(Level.FINE);
    private boolean finerLoggable = logger.isLoggable(Level.FINER);
    private boolean finestLoggable = logger.isLoggable(Level.FINEST);
	//#endif

	/* Create the list and initialization. */
	public KFileSelectorImpl()
	{
		super(null, List.IMPLICIT);

		try {

			//#ifdef DTEST
			if (bDebug) System.out.println("MFS building cmds....");
			//#endif
			//#ifdef DLOGGING
			if (fineLoggable) {logger.fine("MFS building cmds....");}
			//#endif

			super.addCommand(openCommand);
			super.addCommand(cancelCommand);
			super.setSelectCommand(openCommand);
			super.setCommandListener(this);

			//#ifdef DTEST
			if (bDebug) 
			{
				System.out.println("--- file sep: '" + FILE_SEPARATOR + "'");
				System.out.println("--- file sep_alt: '" + FILE_SEPARATOR_ALT + "'");
			}
			//#endif
			//#ifdef DLOGGING
			if (fineLoggable) {logger.fine("--- file sep: '" + FILE_SEPARATOR + "'");}
			if (fineLoggable) {logger.fine("--- file sep_alt: '" + FILE_SEPARATOR_ALT + "'");}
			//#endif
			if (kThread == null) {
				kThread = new Thread(this);
				kThread.start();
			}
		} catch (Throwable t) {
			//#ifdef DLOGGING
			logger.severe("KFileSelectorImpl constructor", t);
			//#endif
			/** Error while executing constructor */
			System.out.println("KFileSelectorFactory getInstance " + t.getMessage());
			t.printStackTrace();
		}

	} //constructor

	/* Get image.  Need retry to handle sometimes failure. */
	private Image getImage(String imagePath) {
		Image rtnImage = null;

		try {
			try {
				// createImage("/icons/(image)") does not always work
				// with the emulator.  so, I do an alternate which is
				// effectively the same thing.
				rtnImage = Image.createImage(imagePath);
			} catch(IOException e) {
				//#ifdef DMIDP20
				//#ifdef DLOGGING
				logger.warning("createImage failed", e);
				//#endif
				InputStream is =
						this.getClass().getResourceAsStream(imagePath);
				rtnImage = Image.createImage(is);
				is.close();
				//#else
				//#ifdef DLOGGING
				logger.severe("--- icons ex: ", imgOpenEx);
				//#endif
				//#endif
			}
		} catch(Exception imgOpenEx) {
			//#ifdef DTEST
			if (bDebug) System.out.println("--- icons ex: " + imgOpenEx);
			//#endif
			//#ifdef DLOGGING
			logger.severe("--- icons ex: ", imgOpenEx);
			//#endif
		} finally {
			return rtnImage;
		}
	}

	/* Initialize.  Get images. */
	public void init() {
		//#ifdef DTEST
		if (bDebug) System.out.println("MFS load images....");
		//#endif
		//ROOT_IMAGE = Image.createImage("root_icon.png");
		FOLDER_IMAGE = UiUtil.getImage(iconDir + "/folder_icon.png");
		FILE_IMAGE = UiUtil.getImage(iconDir + "/file_icon.png");
		UPDIR_IMAGE =  UiUtil.getImage(iconDir + "/up_dir_icon.png");
	}

	// Init fields.
	public void init(MIDlet midlet, String title, String defaultDir,
					 String iconDir)
	{

		super.setTitle(title);
		this.midlet = midlet;
		this.title = title;
		this.defaultDir = defaultDir;
		this.iconDir = iconDir;
		init();
	}

	/* Thread run method used to execute actions.  */
	public void run() {
		try {
			while (true) {
				try {
					if (itemSelected) {
						try {
							openSelected();
						} catch (Throwable t) {
							if (midlet != null) {
								Alert internalAlert = new Alert(
										"Internal problem", 
										"Internal error.  Unable to open.",
										null,
										AlertType.ERROR);
								internalAlert.setTimeout(Alert.FOREVER);
								Display.getDisplay(midlet).setCurrent(
										internalAlert, this );
							}
							//#ifdef DLOGGING
							logger.severe("KFileSelectorImpl openSelected ", t);
							//#endif
							/** Error while executing constructor */
							System.out.println("KFileSelectorFactory openSelected " + t.getMessage());
							t.printStackTrace();
						}
					} else if (cancelCmd) {
						doCleanup();
						parent.childFinished(this);
						cancelCmd = false;
						break;
					}
				} catch (Exception e) {
					//#ifdef DLOGGING
					logger.severe("KFileSelectorImpl run ", e);
					//#endif
				} finally {
					itemSelected = false;
				}

				try {
					Thread.sleep(500L);
				} catch (InterruptedException e) {
				}
			}
		} catch (Throwable t) {
			//#ifdef DLOGGING
			logger.severe("KFileSelectorImpl run ", t);
			//#endif
			/** Error while executing constructor */
			System.out.println("KFileSelectorFactory run " + t.getMessage());
			t.printStackTrace();
		}
	}

	/**
	 * @param The callback client interested in receiving finished status.
	 */
	public void setViewParent(KViewParent aParent)
	{
		if (null == this.parent) {
			FileSystemRegistry.addFileSystemListener(this);
			resetRoots(); //display the root directories
		}
		this.parent = aParent;	
	}//setViewParent


	/**
	 * Cleanup any allocated resources immediately.
	 */
	public void doCleanup()
	{
		this.selectedFile = null;
		this.selectedURL = null;

		if (null != currentRoot) {
			try {currentRoot.close();}
			catch (IOException ioEx) {};
			currentRoot = null;
		}

		fileDataBlock = null;

	}//doCleanup

	public void commandAction(Command c, Displayable d)
	{

		try {
			//#ifdef DTEST
			if (bDebug) System.out.println("cmd action: " + c);
			//#endif
			//#ifdef DLOGGING
			if (fineLoggable) {logger.fine("disp,cmd=" + d.getTitle() + "," + c.getLabel());}
			//#endif

			if (c == openCommand)
			{
				itemSelected = true;
			}
			else if (c == cancelCommand)
			{
				cancelCmd = true;

			}
		} catch (Throwable t) {
			//#ifdef DLOGGING
			logger.severe("KFileSelectorImpl commandAction ", t);
			//#endif
			/** Error while executing constructor */
			System.out.println("KFileSelectorImpl commandAction " + t.getMessage());
			t.printStackTrace();

		}

	}//commandAction


	/* Show current or all root directories.  */
	public void resetRoots()
	{
		//#ifdef DTEST
		if (bDebug) System.out.println("resetRoots...");
		//#endif
		//#ifdef DLOGGING
		if (fineLoggable) {logger.fine("resetRoots...");}
		//#endif

		loadRoots();

		if (defaultDir != null)
		{
			//#ifdef DTEST
			if (bDebug) System.out.println("default.dir: " + defaultDir);
			//#endif
			try
			{
				currentRoot = (FileConnection) Connector.open(  defaultDir,  Connector.READ);
				displayCurrentRoot();
			}
			catch (Exception e)
			{
				//#ifdef DTEST
				if (bDebug) System.out.println("### resetroot ex: " + e);
				//#endif
				//#ifdef DLOGGING
				logger.severe("KFileSelectorImpl constructor ", e);
				//#endif
				displayAllRoots();
			}
		}
		else
		{
			displayAllRoots();
		}
	}//resetRoots




	/* Display all roots. */
	protected void displayAllRoots()
	{
		//#ifdef DTEST
		if (bDebug) System.out.println("displayAllRoots...");
		//#endif

		super.setTitle(title);
		super.deleteAll();
		Enumeration roots = rootsList.elements();
		while (roots.hasMoreElements())
		{
			String root = (String) roots.nextElement();
			//#ifdef DTEST
			if (bDebug) System.out.println("root: " + root);
			//#endif
			super.append(root.substring(1), FOLDER_IMAGE);
		}
		currentRoot = null;
	}//displayAllRoots






	/* Load roots into rootsList array. */
	protected void loadRoots()
	{
		//#ifdef DTEST
		if (bDebug) System.out.println("loadRoots...");
		//#endif

		bCurFolderIsARoot = true;

		if (!rootsList.isEmpty())
		{
			rootsList.removeAllElements();
		}

		try {
			Enumeration roots = FileSystemRegistry.listRoots();
			while (roots.hasMoreElements())
			{
				rootsList.addElement(FILE_SEPARATOR + (String) roots.nextElement());
			}
		} catch (Throwable e) {
			//#ifdef DTEST
			if (bDebug) System.out.println("### load roots: " + e);
			//#endif
		}
	}//loadRoots


	/* Open the selected directory or file. */
	protected void openSelected()
	{

		int selectedIndex = super.getSelectedIndex();
		//#ifdef DTEST
		if (bDebug) System.out.println("openSelected....");
		if (bDebug) System.out.println("selectedIndex: " + selectedIndex);
		//#endif
		//#ifdef DLOGGING
		if (fineLoggable) {logger.fine("openSelected selectedIndex: " + selectedIndex);}
		//#endif

		if (selectedIndex >= 0)
		{
			selectedFile = super.getString(selectedIndex);
			//#ifdef DTEST
			if (bDebug) System.out.println("selectedFile: " + selectedFile);
			//#endif
			//#ifdef DLOGGING
			if (fineLoggable) {logger.fine("openSelected selectedFile: " + selectedFile);}
			//#endif

			if (null != selectedFile)
			{
				if ( selectedFile.endsWith(FILE_SEPARATOR) || selectedFile.endsWith(FILE_SEPARATOR_ALT))
				{
					try
					{
						if (null == currentRoot)
						{
							//#ifdef DTEST
							if (bDebug) System.out.println("new currentRoot...");
							//#endif
							currentRoot = (FileConnection) Connector.open("file:///" + selectedFile, Connector.READ);
						}
						else
						{
							//#ifdef DTEST
							if (bDebug) System.out.println("set cur root conn...");
							//#endif
							currentRoot.setFileConnection(selectedFile);
						}
						displayCurrentRoot();
					}
					catch (SecurityException e)
					{
						//#ifdef DTEST
						if (bDebug) System.out.println("### open file: " + e);
						//#endif
						//#ifdef DLOGGING
						logger.severe("openSelected security exception selected:  " + selectedFile, e);
						logger.severe("openSelected root url selected:  " + currentRoot.getURL(), e);
						//#endif
						if (midlet != null) {
							Alert securityAlert = new Alert(
									"Security problem", 
									"Security problem found either access " +
									" denied or access refused by the user.",
									null,
									AlertType.ERROR);
							securityAlert.setTimeout(Alert.FOREVER);
							Display.getDisplay(midlet).setCurrent(
									securityAlert, this );
						}
						throw e;
					}
					catch (IllegalArgumentException e)
					{
						if (midlet != null) {
							Alert illegalAlert = new Alert(
									"Security problem", 
									"Security problem found either access " +
									" denied or access refused by the user.",
									null,
									AlertType.ERROR);
							illegalAlert.setTimeout(Alert.FOREVER);
							Display.getDisplay(midlet).setCurrent(
									illegalAlert, this );
						}
						//#ifdef DTEST
						if (bDebug) System.out.println("### open file: " + e);
						//#endif
						//#ifdef DLOGGING
						logger.severe("openSelected illegal argument selected:  " + selectedFile, e);
						logger.severe("openSelected root url selected:  " + currentRoot.getURL(), e);
						//#endif
						throw e;
					}
					catch (Exception e)
					{
						//#ifdef DTEST
						if (bDebug) System.out.println("### open file: " + e);
						//#endif
						//#ifdef DLOGGING
						logger.severe("openSelected exception selected:  " + selectedFile, e);
						//#endif
					}
				}
				else if (selectedFile.equals(UP_DIR))
				{
					String curRootName = currentRoot.getPath()  + currentRoot.getName();
					//#ifdef DTEST
					if (bDebug) System.out.println("curRootName: " + curRootName);
					//#endif
					String curShortName = null;
					if (curRootName.charAt(0) == '/') {
						curShortName = curRootName.substring(1);
					}
					//#ifdef DLOGGING
					if (finestLoggable) {logger.finest("curShortName=" + curShortName);}
					if (finestLoggable) {logger.finest("rootsList(0)=" + (String)rootsList.elementAt(0));}
					//#endif

					if( rootsList.contains(curRootName) ||
						((curShortName != null) &&
					    rootsList.contains(FILE_SEPARATOR + curShortName)))
					{
						displayAllRoots();
					}
					else
					{
						try
						{
							currentRoot.setFileConnection(UP_DIR);
							displayCurrentRoot();
						}
						catch (IOException e)
						{
							//#ifdef DLOGGING
							logger.severe("KFileSelectorImpl openSelected at dir " + currentRoot.getPath() + "," + currentRoot.getName(), e);
							//#endif
							//#ifdef DTEST
							if (bDebug) System.out.println("### setfileConn: " + e);
							//#endif
						}
						catch (IllegalArgumentException e)
						{
							//there's something hosed with this path-- jump back to roots
							displayAllRoots();
						}
					}
				}
				else
				{
					//#ifdef DTEST
					if (bDebug) System.out.println("user selected: " + selectedFile);
					//#endif

					//the user has selected a particular file


					//parent.childFinished(this);

					// Clean up in separate thread.  This also saves
					// the selectedURL and sends childFinished.
					parent.addDeferredAction(new KFileSelectorKicker(this));

				}
			}
			else {
				//#ifdef DTEST
				if (bDebug) System.out.println("### no selected file???");
				//#endif

			}
		}
	}//openSelected


	/* Finish completion. */
	protected void doNotifyOpComplete() {

		if (null != currentRoot)
		{
			selectedURL = currentRoot.getURL() + selectedFile;	
			//#ifdef DTEST
			if (bDebug) System.out.println("=== Selected URL: " + selectedURL);
			//#endif

			try {currentRoot.close();}
			catch(IOException ioEx) {}
		}

		currentRoot = null; //reset it
		//selectedFile = null;

		parent.childFinished(this);
	}


	/* Display the current root. */
	protected void displayCurrentRoot()
	{
		//#ifdef DTEST
		if (bDebug) System.out.println("displayCurrentRoot...");
		//#endif

		try
		{
			if (null != currentRoot)
			{
				String rootName = currentRoot.getName();
				if ((rootName == null) || (rootName.length() < 1))
					rootName = selectedFile;

				setTitle("[" + rootName + "]");

			}
			else
				setTitle(title);

			// open the root
			super.deleteAll();
			super.append(UP_DIR, UPDIR_IMAGE);

			// list all dirs
			Enumeration listOfDirs = currentRoot.list("*", false);
			while (listOfDirs.hasMoreElements())
			{
				String currentDir = (String) listOfDirs.nextElement();

				if (currentDir.endsWith(FILE_SEPARATOR)  || currentDir.endsWith(FILE_SEPARATOR_ALT))
				{
					super.append(currentDir, FOLDER_IMAGE);
				}
			}

			if (filePatterns != null) {
				for (int ic = 0; ic > filePatterns.length; ic++) {
					// list all filePatterns files and dont show hidden files
					Enumeration listOfFiles = currentRoot.list(filePatterns[ic], false);
					while (listOfFiles.hasMoreElements())
					{
						String currentFile = (String) listOfFiles.nextElement();
						super.append(currentFile, FILE_IMAGE);
					}
				}
			} else {
				// list all files
				Enumeration listOfFiles = currentRoot.list();
				while (listOfFiles.hasMoreElements())
				{
					String currentFile = (String) listOfFiles.nextElement();
					if (!currentFile.endsWith(FILE_SEPARATOR) &&
							!currentFile.endsWith(FILE_SEPARATOR_ALT)) {
						super.append(currentFile, FILE_IMAGE);
					}
				}
			}

		}
		catch (Exception e)
		{
			//#ifdef DLOGGING
			logger.severe("KFileSelectorImpl constructor", e);
			//#endif
			//#ifdef DTEST
			if (bDebug) System.out.println("### displayRoot ex: " + e);
			//#endif
		}

	}//displayCurrentRoot

	/* Get the selected file name. */
	public String getFileName()
	{
		return selectedFile;
	}//getFileName

	public String getFileMimeType()
	{
		String szMimeType = null;

		if (null != selectedFile)
		{
			if ((selectedFile.indexOf("jpg") > 0) || (selectedFile.indexOf("jpeg") > 0))
				szMimeType = "image/jpeg";
			else if (selectedFile.indexOf("png") > 0)
				szMimeType = "image/png";
			else if (selectedFile.indexOf("gif") > 0)
				szMimeType = "image/gif";
			else if (selectedFile.indexOf("bmp") > 0)
				szMimeType = "image/bmp";
		}

		return szMimeType;
	}//getMimeType

	public Image getThumbnail(int width, int height)
	{
		Image thumbImage = FILE_IMAGE;
		String fileType = getFileMimeType();

		if (null != fileType)
		{
			try {
				byte[] datablock = getFileData(); 
				thumbImage = Image.createImage(datablock,0,datablock.length);
			}
			catch (java.lang.OutOfMemoryError oom) {
				//#ifdef DTEST
				if (bDebug) System.err.println("### OOM on createImage: "  + Runtime.getRuntime().freeMemory());
				//#endif
			}
			catch (Exception ex) {
				//#ifdef DTEST
				if (bDebug)  {
					System.err.println("### Couldn't create image: " + ex);
					ex.printStackTrace();
				}
				//#endif

			}
		}

		if (thumbImage.getWidth() > (2*width)) {
			thumbImage = FILE_IMAGE;
		}

		//#ifdef DTEST
		if (bDebug) System.out.println("...getThumbnail");
		//#endif

		return thumbImage;
	}//getThumbnail

	/* Get data from the selected file. */
	public byte[] getFileData()
	{

		if (null == fileDataBlock)
		{
			if (null != selectedURL)
			{
				try {

					long availSize = 0;

					//#ifdef DTEST
					if (bDebug) System.out.println("selectedURL: " + selectedURL);
					//#endif

					currentRoot = (FileConnection) Connector.open(selectedURL);

					//currentRoot.setFileConnection(selectedFile); //relative to current directory

					//#ifdef DTEST
					if (bDebug) System.out.println(" getting data...");
					//#endif
					availSize = currentRoot.fileSize();
					//#ifdef DTEST
					if (bDebug) System.out.println("file availSize: " + availSize);
					//#endif

					//#ifdef DTEST
					if (bDebug && !currentRoot.canRead()) System.out.println("### can't read???");
					//#endif


					if (availSize > 0)
					{

						try {
							//DataInputStream is = currentRoot.openDataInputStream();
							InputStream is = currentRoot.openInputStream();
							//#ifdef DTEST
							if (bDebug) System.out.println("Creating new file block [" + availSize + "]");
							//#endif

							System.gc();
							fileDataBlock = new byte[(int)availSize];
							//#ifdef DTEST
							if (bDebug) System.out.println("Allocated: " + availSize);
							//#endif

							is.read(fileDataBlock);
							is.close();

							//#ifdef DTEST
							if (bDebug) System.out.println("...data read.");
							//#endif
						}
						catch (IOException ioEx)
						{
							//#ifdef DTEST
							if (bDebug) {
								System.err.println("### ioEx: " + ioEx);

								ioEx.printStackTrace();
							}
							//#endif
						}
						catch (java.lang.OutOfMemoryError oom)
						{
							//#ifdef DTEST
							if (bDebug) System.err.println("### OOM new fileDataBlock: "  + Runtime.getRuntime().freeMemory());
							//#endif
						}
					}

					currentRoot.close(); //no longer needed
					currentRoot = null;
				}
				catch (IOException ioEx)
				{
					//#ifdef DTEST
					if (bDebug) System.out.println("### read file ioex: " + ioEx);
					//#endif
				}
				catch (Exception ex)
				{
					//#ifdef DTEST
					if (bDebug) System.out.println("### read file ex: " + ex);
					//#endif

				}
			}
		}
		else
		{
			//#ifdef DTEST
			if (bDebug) System.out.println("Existing fileDataBlock [" + fileDataBlock.length + "]");
			//#endif
		}

		return fileDataBlock;

	}//getFileData


	/* Method to listen for changes in root. */
	public void rootChanged(int changeType, String strArg)
	{
		//#ifdef DTEST
		if (bDebug) {
			//that's nice...
			if (changeType == FileSystemListener.ROOT_ADDED) 
				System.out.println("=== FileSys: ROOT ADDED");		
			else if (changeType == FileSystemListener.ROOT_REMOVED)
				System.out.println("=== FileSys:ROOT_REMOVED");

			System.out.println("strArg: " + strArg);
		}
		//#endif
	}

	/* Get selected URL. */
	public String getSelectedURL() {
		return (selectedURL);
	}

	/* Set list of file patterns to add to file list.  If null, all files
	   are selected. */
    public void setFilePatterns(String[] filePatterns) {
        this.filePatterns = filePatterns;
    }

	/* Set list of file patterns to add to file list.  */
    public String[] getFilePatterns() {
        return (filePatterns);
    }

    public void setMidlet(MIDlet midlet) {
        this.midlet = midlet;
    }

    public MIDlet getMidlet() {
        return (midlet);
    }

} //class KFileSelectorImpl

/* Class to handle the completion of the OP through a thread. */
final class KFileSelectorKicker
implements Runnable
{
	
	/* Create.  Save target to run. */
	public KFileSelectorKicker(KFileSelectorImpl aTarget) {
		
		target = aTarget;
		
	}

	
	/* Complete the Op when we run if we have a target.  */
	public void run() {
		
		if (null != target) {
			
			target.doNotifyOpComplete();
		}
	}
	
	KFileSelectorImpl target;
}
//#endif
